package com.reminder;

import java.util.List;

import com.reminder.shared.ReminderRequestFactory;
import com.reminder.shared.TaskProxy;
import com.reminder.shared.ReminderRequest;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.ServerFailure;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;
import android.os.Process;

 public class GpsService extends Service {
 private Looper mServiceLooper;
 private ServiceHandler mServiceHandler;
 private static int Notification_ID = 0;
 LocationManager  locationManager;
 Geocoder coder;
 private CountDownTimer timer;
 public static List<TaskProxy> listOfTasks; //list of all tasks downloaded from the server
 public static TaskProxy task;
 private long taskNotifiedId;

  // Handler that receives messages from the thread
  private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
          super(looper);
      }
      @Override
      public void handleMessage(Message msg) {
             	  
    	 // getTasksEvery5Minutes();
      }
  }

  @Override
  public void onCreate() {
    HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();
    
    // Get the HandlerThread's Looper and use it for our Handler 
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
  } 

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

      // For each start request, send a message to start a job and deliver the
      // start ID so we know which request we're stopping when we finish the job
      Message msg = mServiceHandler.obtainMessage();
      msg.arg1 = startId;
      mServiceHandler.sendMessage(msg);
      Toast.makeText(this, "is in onStartCommand", Toast.LENGTH_SHORT).show();
      getTasksEvery5Minutes(); 

      return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
      // We don't provide binding, so return null
      return null;
  }
  
  @Override
  public void onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); 
  }
  
private LocationListener locationListener = new LocationListener() {
	  
	  public void onLocationChanged(Location location) {
		  SendNotificationToTasksWithinTheDistance(location.getLatitude(), location.getLongitude(), 50f);
      }
	  
	  public void onProviderDisabled(String provider) {
      }
	  public void onProviderEnabled(String provider) {
      }
	  public void onStatusChanged(String provider, int status, Bundle extras) {
      }
  };
  
  
  public void doOnLocationChange(){
	  locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
      coder = new Geocoder(getApplicationContext());
	  locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
  }
  
  private void sendNotification(TaskProxy sendToTask){
		//Get a reference to the NotificationManager
		 String ns = Context.NOTIFICATION_SERVICE;
	 	 NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
	 	 int icon = R.drawable.ic_title_add;//change that
	 	 CharSequence tickerText = "Task update";
	 	 long when = System.currentTimeMillis();
	 	 Notification notification = new Notification(icon, tickerText, when);
	 	 
	 	 //Define the notification's message and PendingIntent
	 	 Context context = getApplicationContext();
	 	 CharSequence contentTitle = "My task update";
	 	 CharSequence contentText = "Task update!";
	 	 Intent notificationIntent = new Intent(this, ViewTaskActivity.class);
	 	 notificationIntent.putExtra("geoTask", 1); //?
	 	 notificationIntent.putExtra("count", 0);   //?
	 	 notificationIntent.putExtra("taskId", sendToTask.getId());
	 	 
	 	 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
	 	 notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
	 	 Notification_ID += 1;
	 	 mNotificationManager.notify(Notification_ID, notification);
	  }
  
  public void getNewTasks() { //download the tasks from the server
	  	ReminderRequestFactory factory = (ReminderRequestFactory) Util
	              .getRequestFactory(GpsService.this,
	                      ReminderRequestFactory.class);
	      ReminderRequest request = factory.taskRequest();
	      request.findAllNotNotified().fire(new Receiver<List<TaskProxy>>() {
				@Override
				public void onSuccess(List<TaskProxy> result) {
					// if success
					listOfTasks = result; //the listOfTasks holds the tasks 
					doOnLocationChange();
				}
				
				@Override
				public void onFailure(ServerFailure failure) {
					// If error
				}
			});
	 }
  
  public void SendNotificationToTasksWithinTheDistance(double lat, double lngt, double radius){
	  double endLatitude = lat;
	  double endLongtitude = lngt;
	  float[] result=new float[1]; //to store the result of the distanceBetween()
	  int nextTask = 0; 
	while(nextTask < listOfTasks.size()) {
			double longtitude = listOfTasks.get(nextTask).getLongitude();
			double latitude = listOfTasks.get(nextTask).getLatitude();
	     //calculate the distance
	     Location.distanceBetween(latitude, longtitude, endLatitude, endLongtitude, result);
	     //compare the distance with the radius
	     if (result[0] <= radius) {
	    	    sendNotification(listOfTasks.get(nextTask));
	    	    taskNotifiedId = listOfTasks.get(nextTask).getId();
	    	    updateNotifiedTasks();
	     }
	     nextTask++;
	}
  }
  
  public void getTasksEvery5Minutes(){
	  timer = new CountDownTimer(1000*60*5, 1000*60){
		  public void onTick(long millisUntilFinished){
			  synchronized (this) {
				  try {
					  getNewTasks();
				  } catch (Exception e) {
				  	}
              }
		  }
		  public void onFinish(){
			  timer.start();
		  }
	  }.start();
  }
  
  public void updateNotifiedTasks(){
	  new AsyncTask<Void, Void, Void>() {

          @Override
          protected Void doInBackground(Void... arg0) {
  	ReminderRequestFactory factory = (ReminderRequestFactory) Util
              .getRequestFactory(GpsService.this,
                      ReminderRequestFactory.class);
      ReminderRequest request = factory.taskRequest();
      request.updateTasksNotified(taskNotifiedId).fire();
      return null;
          }

      }.execute();
 }

}
